package net.stogi.common.api.exception;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Generic holder of error-related information. For given field name it holds
 * error message property key name and error message arguments.
 */
public class Messages implements Serializable {

	private static final long serialVersionUID = -2878562239512504162L;

	private Map<String, String> errors;

	private Map<String, List<String>> errorsArguments;

	private Map<String, String> infos;

	private Map<String, List<String>> infosArguments;

	private Map<String, String> warns;

	private Map<String, List<String>> warnsArguments;

	public Messages() {
		errors = new HashMap<String, String>();
		errorsArguments = new HashMap<String, List<String>>();
		infos = new HashMap<String, String>();
		infosArguments = new HashMap<String, List<String>>();
		warns = new HashMap<String, String>();
		warnsArguments = new HashMap<String, List<String>>();
	}

	public void error(String field, String errorCode) {
		errors.put(field, errorCode);
	}

	public void error(String field, String errorCode, String... argumentArray) {
		errors.put(field, errorCode);
		errorsArguments.put(errorCode, convertArgumentArrayToArgumentList(argumentArray));
	}

	public List<String> getErrorArguments(String messageCode) {
		return new ArrayList<String>(errorsArguments.get(messageCode));
	}

	public Map<String, String> getErrors() {
		return new HashMap<String, String>(errors);
	}

	public List<String> getInfoArguments(String messageCode) {
		return new ArrayList<String>(infosArguments.get(messageCode));
	}

	public Map<String, String> getInfos() {
		return new HashMap<String, String>(infos);
	}

	public List<String> getWarnArguments(String messageCode) {
		return new ArrayList<String>(warnsArguments.get(messageCode));
	}

	public Map<String, String> getWarns() {
		return new HashMap<String, String>(warns);
	}

	public boolean hasErrors() {
		return !errors.isEmpty();
	}

	public boolean hasInfos() {
		return !infos.isEmpty();
	}

	public boolean hasWarns() {
		return !warns.isEmpty();
	}

	public void info(String field, String infoCode) {
		infos.put(field, infoCode);
	}

	public void info(String field, String infoCode, String... argumentArray) {
		infos.put(field, infoCode);
		infosArguments.put(infoCode, convertArgumentArrayToArgumentList(argumentArray));
	}

	public List<String> listErrorCodes() {
		return new ArrayList<String>(errors.values());
	}

	public List<String> listInfoCodes() {
		return new ArrayList<String>(infos.values());
	}

	public List<String> listWarnCodes() {
		return new ArrayList<String>(warns.values());
	}

	public void warn(String field, String warnCode) {
		warns.put(field, warnCode);
	}

	public void warn(String field, String warnCode, String... argumentArray) {
		warns.put(field, warnCode);
		warnsArguments.put(warnCode, convertArgumentArrayToArgumentList(argumentArray));
	}

	private List<String> convertArgumentArrayToArgumentList(String[] argumentArray) {
		if (argumentArray == null) {
			throw new IllegalArgumentException("Parameter 'argumentArray' can not be null");
		}
		ArrayList<String> argumentList = new ArrayList<String>();
		for (String argument : argumentArray) {
			argumentList.add(argument);
		}
		return argumentList;
	}
}
